package com.hy.${packageCode}.shared.utils;

import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

public class CommonUtils {
    private static final String HEX_CODE = "0123456789ABCDEF";

    private CommonUtils() {
    }

    public static <T, U> void copyProperties(T from, U to, String... ignores) {
        BeanUtils.copyProperties(from, to, ignores);
    }

    public static <T, U> U copyProperties(T from, Class<U> to, String... ignores) {
        U bean = BeanUtils.instantiateClass(to);
        copyProperties(from, bean, ignores);
        return bean;
    }

    public static String toHexString(byte[] buffers) {
        StringBuilder hexString = new StringBuilder();
        for (byte buffer : buffers) {
            String hex = Integer.toHexString(buffer & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            hexString.append(hex.toUpperCase());
        }
        return hexString.toString();
    }

    public static byte[] toHexBytes(final String hexString) {
        if (hexString == null || hexString.length() == 0) {
            return new byte[]{};
        }
        String newHexString = hexString.toUpperCase();
        int length = newHexString.length() / 2;
        char[] hexChars = newHexString.toCharArray();
        byte[] d = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]) & 0xff);
        }
        return d;
    }

    public static <T> boolean isEqual(Collection<T> one, Collection<T> two) {
        if (CollectionUtils.isEmpty(one) && CollectionUtils.isEmpty(two)) {
            return true;
        }
        if (CollectionUtils.isEmpty(one) || CollectionUtils.isEmpty(two)) {
            return false;
        }
        if (one.size() != two.size()) {
            return false;
        }
        return one.containsAll(two);
    }

    public static <K, V> boolean isEqual(Map<K, V> one, Map<K, V> two) {
        if (CollectionUtils.isEmpty(one) && CollectionUtils.isEmpty(two)) {
            return true;
        }
        if (CollectionUtils.isEmpty(one) || CollectionUtils.isEmpty(two)) {
            return false;
        }
        if (one.size() != two.size()) {
            return false;
        }
        for (Map.Entry<K,V> entry : one.entrySet()) {
            K key = entry.getKey();
            if (!two.containsKey(key) || Objects.equals(entry.getValue(), two.get(key))) {
                return false;
            }
        }
        return true;
    }

    public static boolean toSafeBoolean(Boolean value) {
        return value != null && value;
    }

    public static boolean isLong(String checkValue) {
        if (!StringUtils.hasText(checkValue)) {
            return false;
        }
        try {
            Long.parseLong(checkValue);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    public static boolean isDouble(String checkValue) {
        if (!StringUtils.hasText(checkValue)) {
            return false;
        }
        try {
            Double.parseDouble(checkValue);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    public static <T> Stream<T> stream(Iterable<T> iterable) {
        return StreamSupport.stream(iterable.spliterator(), false);
    }

    public static <T> Stream<T> stream(Iterator<T> iterator) {
        if (!iterator.hasNext()) {
            return Stream.empty();
        }
        return stream(() -> iterator);
    }



    private static byte charToByte(char c) {
        return (byte) HEX_CODE.indexOf(c);
    }


}
